우분투(Ubuntu) 서버 환경에서 Mistral LLM을 구축하고 파이썬 API 서버(FastAPI)로 띄우는 전체 과정을 순서대로 정리해 드립니다.

하드웨어(GPU 유무, RAM 용량)에 구애받지 않고 가장 안정적으로 동작하는 **표준 라이브러리(`transformers`) 기준**으로 작성되었습니다.

---

## 1단계: 가상환경 및 필수 라이브러리 설치

시스템 파이썬을 보호하고 의존성 충돌을 막기 위해 가상환경(Conda)을 세팅합니다.

**1. Conda 가상환경 생성 및 활성화**

```bash
conda create -n mistral-env python=3.10 -y
conda activate mistral-env

```

**2. 필수 파이썬 패키지 설치**
AI 구동 커널, 웹 서버 라이브러리, 허깅페이스 통신 모듈을 한 번에 설치합니다.

```bash
pip install torch transformers accelerate fastapi uvicorn huggingface_hub

```

## 2단계: Hugging Face 인증 및 모델 다운로드

Mistral 7B 모델은 허깅페이스(Hugging Face)를 통해 배포되므로 토큰 인증이 필요합니다.

**1. 토큰 로그인**

```bash
python -m huggingface_hub.cli login

```

* `Token:` 프롬프트가 뜨면 허깅페이스 사이트(Settings -> Access Tokens)에서 발급받은 토큰을 붙여넣고 엔터를 칩니다. (보안상 화면에 글자가 보이지 않습니다.)
* `Add token as git credential? (y/n)` 질문에는 `n`을 입력합니다.

**2. 모델 다운로드 경로 준비**

```bash
mkdir -p ~/mistral_models/7B-Instruct-v0.3

```

**3. 모델 다운로드 실행 (약 15GB)**

```bash
python -m huggingface_hub.cli download mistralai/Mistral-7B-Instruct-v0.3 --local-dir ~/mistral_models/7B-Instruct-v0.3 --local-dir-use-symlinks False

```

## 3단계: 파이썬 웹 서버 코드 작성 (`serve_mistral.py`)

FastAPI를 사용하여 외부에서 API로 LLM에 질문을 던질 수 있도록 서버 코드를 작성합니다.

**1. 파이썬 파일 생성**

```bash
nano serve_mistral.py

```

**2. 서버 코드 붙여넣기**
메모리 부족(Killed)이나 GPU(CUDA) 에러를 방지하기 위해 용량을 절반으로 줄이는 `float16` 옵션과 자동 디스크 오프로딩이 적용된 코드입니다.

```python
import warnings
warnings.filterwarnings("ignore")

from fastapi import FastAPI
from fastapi.responses import JSONResponse
from pydantic import BaseModel
import uvicorn
import torch
import os
from transformers import AutoModelForCausalLM, AutoTokenizer
import time

# =========================================================
# [시스템] AI 모델 로드
# =========================================================
model_path = os.path.expanduser("~/mistral_models/7B-Instruct-v0.3")
print("=== AI 모델 로딩 중... ===")

try:
    tokenizer = AutoTokenizer.from_pretrained(model_path)
    
    # 메모리 최적화 및 장치 자동 할당
    model = AutoModelForCausalLM.from_pretrained(
        model_path,
        device_map="auto",          # GPU가 없으면 자동으로 CPU/RAM 사용
        torch_dtype=torch.float16,  # 메모리 사용량 절반 감소
        low_cpu_mem_usage=True
    )
    print("=== AI 준비 완료 ===")
except Exception as e:
    print(f"!!! 모델 로드 실패: {e}")
    exit()

app = FastAPI()

class ChatRequest(BaseModel):
    prompt: str

# =========================================================
# [API] 메인 엔드포인트
# =========================================================
@app.post("/chat")
async def chat_endpoint(request: ChatRequest):
    try:
        user_input = request.prompt
        print(f"\n>> 질문: {user_input}")

        # 메시지 템플릿 적용
        messages = [{"role": "user", "content": user_input}]
        prompt = tokenizer.apply_chat_template(messages, tokenize=False, add_generation_prompt=True)
        
        # 모델 장치(CPU/GPU)에 맞게 입력값 전달
        inputs = tokenizer(prompt, return_tensors="pt").to(model.device)

        start_time = time.time()
        print("   (AI 연산 시작...)")
        
        # 텍스트 생성
        with torch.no_grad():
            outputs = model.generate(
                **inputs,
                max_new_tokens=512,
                temperature=0.1,
                do_sample=True,
                pad_token_id=tokenizer.eos_token_id
            )
        
        print(f"   (연산 완료: {time.time() - start_time:.2f}초)")

        # 결과 디코딩 (입력된 프롬프트 제외)
        generated_text = tokenizer.decode(outputs[0][inputs.input_ids.shape[1]:], skip_special_tokens=True)
        
        return JSONResponse(content={"response": generated_text.strip()})

    except Exception as e:
        print(f"Server Error: {e}")
        return JSONResponse(content={"response": "시스템 오류가 발생했습니다."}, status_code=500)

if __name__ == "__main__":
    uvicorn.run(app, host="0.0.0.0", port=8000)

```

* 저장 후 종료: `Ctrl + O` -> `Enter` -> `Ctrl + X`

## 4단계: 무중단 백그라운드 실행 (`tmux`)

SSH 터미널 접속을 끊어도 서버가 계속 켜져 있도록 가상 화면(`tmux`)을 활용합니다.

**1. 백그라운드 세션 생성**

```bash
tmux new -s aiserver

```

**2. 환경 활성화 및 서버 실행**
새로 열린 가상 화면에서 서버를 켭니다.

```bash
conda activate mistral-env
python serve_mistral.py

```

**3. 가상 화면 빠져나오기 (서버 유지)**
서버가 정상적으로 켜진 것을 확인한 뒤, 키보드에서 `Ctrl + B`를 누르고 손을 뗀 다음 `D`를 누릅니다.
이제 터미널 프로그램을 종료해도 백그라운드에서 AI 서버가 정상적으로 요청을 대기합니다.

---

> **운영 팁:** 프로세스가 램 용량을 초과해 강제 종료(Killed)되는 현상이 발생한다면, 우분투 하드디스크 공간을 램처럼 활용하는 **스왑 메모리(Swap Memory)**를 16GB 이상 할당해 주어야 모델이 죽지 않고 연산을 완료할 수 있습니다.